package com.adingxiong.cft.util;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @ClassName ZipUtils
 * @Description   文件压缩工具包       使用场景
 *  多层级目录文件压缩
 * @Author xiongchao
 * @Date 2020/12/6 15:46
 **/
@Slf4j
public class ZipUtils {

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public void zip(String sourceUrl, HttpServletResponse response,String zipName){
        ZipOutputStream out = null;
        BufferedOutputStream bos = null;
        log.info("开始压缩文件:{}", sdf.format(new Date()));
        File sourceFile = new File(sourceUrl);
        try {
            //将zip以流的形式输出到前台
            response.setHeader("content-type", "application/octet-stream");
            response.setCharacterEncoding("utf-8");
            // 设置浏览器响应头对应的Content-disposition
            //参数中 testZip 为压缩包文件名，尾部的.zip 为文件后缀
            response.setHeader("Content-disposition",
                    "attachment;filename=" + new String(zipName.getBytes("gbk"), "iso8859-1")+".zip");
            //创建zip输出流
            out = new ZipOutputStream(response.getOutputStream());
            //创建缓冲输出流
            bos = new BufferedOutputStream(out);
            //调用压缩函数
            compress(out, bos, sourceFile, sourceFile.getName());
            out.flush();
            log.info("压缩完成:{}" ,sdf.format(new Date()));
        } catch (Exception e) {
            log.error("ZIP压缩异常："+e.getMessage(),e);
        } finally {
            deleteFile(sourceFile);
            close(bos,out);
        }
    }
    public static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base){
        FileInputStream fos = null;
        BufferedInputStream bis = null;
        try {
            //如果路径为目录（文件夹）
            if (sourceFile.isDirectory()) {
                //取出文件夹中的文件（或子文件夹）
                File[] flist = sourceFile.listFiles();
                //如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
                if (flist.length == 0) {
                    out.putNextEntry(new ZipEntry(base + File.separator));
                } else {
                    //如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
                    for (int i = 0; i < flist.length; i++) {
                        compress(out, bos, flist[i], base + File.separator + flist[i].getName());
                    }
                }
            } else {
                //如果不是目录（文件夹），即为文件，则先写入目录进入点，之后将文件写入zip文件中
                out.putNextEntry(new ZipEntry(base));
                fos = new FileInputStream(sourceFile);
                bis = new BufferedInputStream(fos);
                byte []  buffer = new byte[1024];
                int tag;
                //将源文件写入到zip文件中
                while ((tag = bis.read(buffer)) != -1) {
                    out.write(buffer, 0 ,tag);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(bis,fos);
        }
    }

    public void chenkFile(File file,String path){
        try {
            if (file.exists()){
                //如果文件不存在
                if (!file.isDirectory()){
                    file.createNewFile();
                }
            }else {
                //如果目录不存在
                //创建指定目录文件对象
                File file1 = new File(path);
                file1.mkdirs();//创建目录
                file.createNewFile();//创建文件
            }
        } catch (IOException e) {
            log.error(e.getMessage(),e);
        }
    }

    public void deleteFile(File file) {
        log.info("开始删除文件{}" ,sdf.format(new Date()));
        new Thread(() -> {
            if (file.exists()) {
                if (file.isFile()) {
                    file.delete();
                } else if (file.isDirectory()) {
                    File[] files = file.listFiles();
                    for (int i = 0; i < files.length; i++) {
                        this.deleteFile(files[i]);
                    }
                    file.delete();
                }
            } else {
                System.out.println("所删除的文件不存在");
            }
        }).start();
        log.info("删除文件完成{}" ,sdf.format(new Date()));
    }


    public static void close(Closeable...ios){
        for(Closeable io : ios){
            if(io != null) {
                try {
                    io.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    log.error("流关闭异常");
                }
            }
        }
    }
}
